home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / DIBLK.PAK / MYFILE.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  8KB  |  299 lines

  1. //  myfile.cpp
  2. //
  3. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  4. //  the following functions:
  5. //
  6. //  SaveDIB()           - Saves the specified dib in a file
  7. //  ReadDIBFile()       - Loads a DIB from a file
  8. //
  9. //
  10. // This is a part of the Microsoft Foundation Classes C++ library.
  11. // Copyright (C) 1992-1995 Microsoft Corporation
  12. // All rights reserved.
  13. //
  14. // This source code is only intended as a supplement to the
  15. // Microsoft Foundation Classes Reference and related
  16. // electronic documentation provided with the library.
  17. // See these sources for detailed information regarding the
  18. // Microsoft Foundation Classes product.
  19.  
  20. #include "stdafx.h"
  21. #include <math.h>
  22. #include <io.h>
  23. #include <direct.h>
  24. #include "dibapi.h"
  25.  
  26. /*
  27.  * Dib Header Marker - used in writing DIBs to files
  28.  */
  29. #define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
  30.  
  31. #ifdef _MAC
  32. #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
  33. #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
  34. void ByteSwapHeader(BITMAPFILEHEADER* bmiHeader);
  35. void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header);
  36. #endif
  37.  
  38. /*************************************************************************
  39.  *
  40.  * SaveDIB()
  41.  *
  42.  * Saves the specified DIB into the specified CFile.  The CFile
  43.  * is opened and closed by the caller.
  44.  *
  45.  * Parameters:
  46.  *
  47.  * HDIB hDib - Handle to the dib to save
  48.  *
  49.  * CFile& file - open CFile used to save DIB
  50.  *
  51.  * Return value: TRUE if successful, else FALSE or CFileException
  52.  *
  53.  *************************************************************************/
  54.  
  55.  
  56. BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
  57. {
  58.     BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  59.     LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure
  60.     DWORD dwDIBSize;
  61.  
  62.     if (hDib == NULL)
  63.         return FALSE;
  64.  
  65.     /*
  66.      * Get a pointer to the DIB memory, the first of which contains
  67.      * a BITMAPINFO structure
  68.      */
  69.     lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
  70.     if (lpBI == NULL)
  71.         return FALSE;
  72.  
  73.     if (!IS_WIN30_DIB(lpBI))
  74.     {
  75.         ::GlobalUnlock((HGLOBAL) hDib);
  76.         return FALSE;       // It's an other-style DIB (save not supported)
  77.     }
  78.  
  79.     /*
  80.      * Fill in the fields of the file header
  81.      */
  82.  
  83.     /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
  84.     bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"
  85.  
  86.     // Calculating the size of the DIB is a bit tricky (if we want to
  87.     // do it right).  The easiest way to do this is to call GlobalSize()
  88.     // on our global handle, but since the size of our global memory may have
  89.     // been padded a few bytes, we may end up writing out a few too
  90.     // many bytes to the file (which may cause problems with some apps).
  91.     //
  92.     // So, instead let's calculate the size manually (if we can)
  93.     //
  94.     // First, find size of header plus size of color table.  Since the
  95.     // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  96.     // the size of the structure, let's use this.
  97.  
  98.     dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation
  99.  
  100.     // Now calculate the size of the image
  101.  
  102.     if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
  103.     {
  104.         // It's an RLE bitmap, we can't calculate size, so trust the
  105.         // biSizeImage field
  106.  
  107.         dwDIBSize += lpBI->biSizeImage;
  108.     }
  109.     else
  110.     {
  111.         DWORD dwBmBitsSize;  // Size of Bitmap Bits only
  112.  
  113.         // It's not RLE, so size is Width (DWORD aligned) * Height
  114.  
  115.         dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
  116.  
  117.         dwDIBSize += dwBmBitsSize;
  118.  
  119.         // Now, since we have calculated the correct size, why don't we
  120.         // fill in the biSizeImage field (this will fix any .BMP files which
  121.         // have this field incorrect).
  122.  
  123.         lpBI->biSizeImage = dwBmBitsSize;
  124.     }
  125.  
  126.  
  127.     // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  128.  
  129.     bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  130.     bmfHdr.bfReserved1 = 0;
  131.     bmfHdr.bfReserved2 = 0;
  132.  
  133.     /*
  134.      * Now, calculate the offset the actual bitmap bits will be in
  135.      * the file -- It's the Bitmap file header plus the DIB header,
  136.      * plus the size of the color table.
  137.      */
  138.     bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
  139.                                               + PaletteSize((LPSTR)lpBI);
  140. #ifdef _MAC
  141.     ByteSwapHeader(&bmfHdr);
  142.  
  143.     // First swap the size field
  144.     *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  145.  
  146.     // Now swap the rest of the structure (we don't save < Win30 files)
  147.     ByteSwapInfo((LPSTR)lpBI, TRUE);
  148. #endif
  149.  
  150.     TRY
  151.     {
  152.         // Write the file header
  153.         file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  154.         //
  155.         // Write the DIB header and the bits
  156.         //
  157.         file.WriteHuge(lpBI, dwDIBSize);
  158.     }
  159.     CATCH (CFileException, e)
  160.     {
  161. #ifdef _MAC
  162.         // Swap everything back
  163.         *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  164.         ByteSwapInfo((LPSTR)lpBI, TRUE);
  165. #endif
  166.         ::GlobalUnlock((HGLOBAL) hDib);
  167.         THROW_LAST();
  168.     }
  169.     END_CATCH
  170.  
  171. #ifdef _MAC
  172.     // Swap everything back
  173.     *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  174.     ByteSwapInfo((LPSTR)lpBI, TRUE);
  175. #endif
  176.  
  177.     ::GlobalUnlock((HGLOBAL) hDib);
  178.     return TRUE;
  179. }
  180.  
  181.  
  182. /*************************************************************************
  183.  
  184.   Function:  ReadDIBFile (CFile&)
  185.  
  186.    Purpose:  Reads in the specified DIB file into a global chunk of
  187.              memory.
  188.  
  189.    Returns:  A handle to a dib (hDIB) if successful.
  190.              NULL if an error occurs.
  191.  
  192.   Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
  193.              from the end of the BITMAPFILEHEADER structure on is
  194.              returned in the global memory handle.
  195.  
  196. *************************************************************************/
  197.  
  198.  
  199. HDIB WINAPI ReadDIBFile(CFile& file)
  200. {
  201.     BITMAPFILEHEADER bmfHeader;
  202.     DWORD dwBitsSize;
  203.     HDIB hDIB;
  204.     LPSTR pDIB;
  205.  
  206.     /*
  207.      * get length of DIB in bytes for use when reading
  208.      */
  209.  
  210.     dwBitsSize = file.GetLength();
  211.  
  212.     /*
  213.      * Go read the DIB file header and check if it's valid.
  214.      */
  215.     if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  216.         return NULL;
  217.  
  218. #ifdef _MAC
  219.     ByteSwapHeader(&bmfHeader);
  220. #endif
  221.     if (bmfHeader.bfType != DIB_HEADER_MARKER)
  222.         return NULL;
  223.  
  224.     /*
  225.      * Allocate memory for DIB
  226.      */
  227.     hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  228.     if (hDIB == 0)
  229.     {
  230.         return NULL;
  231.     }
  232.     pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  233.  
  234.     /*
  235.      * Go read the bits.
  236.      */
  237.     if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
  238.         dwBitsSize - sizeof(BITMAPFILEHEADER) )
  239.     {
  240.         ::GlobalUnlock((HGLOBAL) hDIB);
  241.         ::GlobalFree((HGLOBAL) hDIB);
  242.         return NULL;
  243.     }
  244. #ifdef _MAC
  245.     // First swap the size field
  246.     *((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB));
  247.  
  248.     // Now swap the rest of the structure
  249.     ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB));
  250. #endif
  251.     ::GlobalUnlock((HGLOBAL) hDIB);
  252.     return hDIB;
  253. }
  254.  
  255.  
  256. #ifdef _MAC
  257. void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader)
  258. {
  259.     bmfHeader->bfType = SWAPWORD(bmfHeader->bfType);
  260.     bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize);
  261.     bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits);
  262. }
  263.  
  264.  
  265. void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header)
  266. {
  267.     // Note this doesn't swap the bcSize/biSize field.  It assumes that the
  268.     // size field was swapped during read or while setting the fWin30Header
  269.     // flag.
  270.  
  271.     if (fWin30Header)
  272.     {
  273.         LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader);
  274.  
  275.         //lpBMIH->biSize = SWAPLONG(lpBMIH->biSize);
  276.         lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth);
  277.         lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight);
  278.         lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes);
  279.         lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount);
  280.         lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression);
  281.         lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage);
  282.         lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter);
  283.         lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter);
  284.         lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed);
  285.         lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant);
  286.     }
  287.     else
  288.     {
  289.         LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader);
  290.  
  291.         lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth);
  292.         lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight);
  293.         lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes);
  294.         lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount);
  295.     }
  296. }
  297.  
  298. #endif
  299.